/*
 * circularQueue.cpp
 *
 *  Created on: Jul 18, 2012
 *      Author: jh238d
 */


#include <pthread.h>
#include <iostream>
using namespace std;
#define DEFAULT_SIZE 100

class CircularQueue {
private:
	int *q; //array
	int head; //head position
	int tail; //tail position
	int cap; //array occupation
	int size; //array size
	pthread_mutex_t mutex; //mutual exclusion

public:
	CircularQueue(int n) {
		initialize(n);
	}
	virtual ~CircularQueue() {
		delete[] q;
		q = NULL;
		pthread_mutex_destroy(&mutex);
	}

	void initialize(int n) {
		//invalid size
		if (n < 0)
			size = DEFAULT_SIZE;
		else
			size = n;

		q = new int[size];
		head = 0;
		tail = -1;
		cap = 0;
		pthread_mutex_init(&mutex, NULL);
	}

	bool enqueue(int x) {
		bool queued = false;
		pthread_mutex_lock(&mutex);
		// queue is full
		if (cap == size) {
			queued = false;
		} else {
			tail++;
			q[tail % size] = x;
			cap++;
			queued = true;
		}
		pthread_mutex_unlock(&mutex);
		return queued;
	}

	int dequeue() {
		int front = 0;
		pthread_mutex_lock(&mutex);
		try {
			if (cap == 0) {
				throw "Exception: empty queue cannot be dequeued!";
				pthread_mutex_unlock(&mutex);
			} else {
				front = q[head];
				head++;
				head %= size;
				cap--;
			}
		}
		catch (char const *str) {
			cout << str << endl;
		}
		pthread_mutex_unlock(&mutex);
		return front;
	}
};

/*int main() throw () {
	CircularQueue* c = new CircularQueue(5);
	cout << c->enqueue(4) << endl;
//c->enqueue(1);
	cout << c->dequeue() << endl;
	c->dequeue();
}*/

